package com.ckzp.core.util;

import com.alibaba.fastjson.JSON;
import com.ckzp.core.ConfigUtil;
import com.ckzp.core.Results;
import com.ckzp.jfinal.system.util.LoginUtil;
import io.jsonwebtoken.*;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by 51594 on 2022/7/27.
 */
public class JwtUtil {

    /**
     *
     */
    public static long EXP_DATE = 24 * 60 * 60 * 1000;
    /**
     *
     */
    protected static boolean DEBUG = ConfigUtil.DEBUG();

    /**
     * 签发JWT
     *
     * @param id
     * @param subject   可以是JSON数据 尽可能少
     * @param ttlMillis
     * @return String
     */
    public static String createJWT(String id, JwtSubject subject, long ttlMillis) {
        return createJWT(id, subject.toJson(), ttlMillis);
    }


    /**
     * 签发JWT
     *
     * @param uid
     * @return String
     */
    public static String createJWT(int uid) {
        JwtUtil.JwtSubject js = new JwtUtil.JwtSubject();
        js.setUserid(uid);
        return createJWT("jwt", js, EXP_DATE);
    }

    /**
     * 签发JWT
     *
     * @param id
     * @param subject   可以是JSON数据 尽可能少
     * @param ttlMillis
     * @return String
     */
    public static String createJWT(String id, String subject, long ttlMillis) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        SecretKey secretKey = generalKey();
        JwtBuilder builder = Jwts.builder()
                .setId(id)
                .setSubject(subject)   // 主题
                .setIssuer("user")     // 签发者
                .setIssuedAt(now)      // 签发时间
                .signWith(signatureAlgorithm, secretKey); // 签名算法以及密匙
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date expDate = new Date(expMillis);
            System.out.println(expDate);
            builder.setExpiration(expDate); // 过期时间
        }
        return builder.compact();
    }

    /**
     * 验证JWT
     *
     * @param jwtStr
     * @return
     */
    public static Results validateJWT(String jwtStr) {
        Results result = new Results(0);
        Claims claims = null;
        try {
            claims = parseJWT(jwtStr);
            result.setCode(0);
            result.setMsg("验证成功");
            result.setMessage(claims.getSubject());
            result.setObject(JSON.parseObject(claims.getSubject(), JwtSubject.class));
        } catch (ExpiredJwtException e) {
            e.printStackTrace();
            result.setCode(91);
            result.setMsg("登陆已过期");
            result.setMessage(e.getMessage());
        } catch (SignatureException e) {
            result.setCode(92);
            result.setMsg("无效TOKEN");
            result.setMessage(e.getMessage());
        } catch (Exception e) {
            result.setCode(93);
            result.setMsg("你未登陆");
            result.setMessage(e.getMessage());
        }
//        if (result.getCode() == 0) {
//            if (JwtPool.checkJwt(jwtStr)) {
//                result.setCode(95);
//                result.setMsg("登陆已注销");
//                result.setMessage("登陆已注销");
//                result.setObject(new JwtSubject());
//            }
//        }
        return result;
    }

    /**
     * 信息
     *
     * @param jwtStr
     * @return
     */
    public static JwtSubject getJwtInfo(String jwtStr) {
        Results result = validateJWT(jwtStr);
        try {
            return result.getObject(JwtUtil.JwtSubject.class);
        } catch (Exception e) {
            e.printStackTrace();
            return new JwtSubject();
        }
    }

    /**
     * 从head中取jwt
     *
     * @param request
     * @return
     */
    public static JwtSubject getJwtInfo(HttpServletRequest request) {
        Results result = validateJWT(request.getHeader("X-Jwt-Token"));
        try {
            return result.getObject(JwtUtil.JwtSubject.class);
        } catch (Exception e) {
            return new JwtSubject();
        }
    }


    /**
     * 取得jwt用户信息
     *
     * @param jwt
     * @return
     */
    public static int getUserId(String jwt) {
        if (jwt == null || jwt.length() == 0) return 0;
        Results results = JwtUtil.validateJWT(jwt);
        if (results.getCode() == 0) {
            JwtUtil.JwtSubject js = results.getObject(JwtUtil.JwtSubject.class);
            return js.getUserid();
        }
        return 0;
    }

    /**
     * @param result
     * @return
     */
    public static JwtSubject getJwtInfo(Results result) {
        try {
            return result.getObject(JwtUtil.JwtSubject.class);
        } catch (Exception e) {
            return new JwtSubject();
        }
    }

    /**
     * @return
     */
    public static SecretKey generalKey() {
        byte[] encodedKey = ConfigUtil.getProperty("JWT_SECERT", "DEFAULT_KEY_9423156").getBytes();
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }

    /**
     * 解析JWT字符串
     *
     * @param jwt
     * @return
     * @throws Exception
     */
    public static Claims parseJWT(String jwt) throws Exception {
        SecretKey secretKey = generalKey();
        return Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(jwt)
                .getBody();
    }

    public static class JwtSubject {

        public String id;//会话ID
        public int userid = 0;
        public int pid = 0;
        public int deptid = 0;
        public int orgid = 0;
        public int tempid = 0;
        public String username;
        public String roles;
        public String posts;
        public long lastlogin = 0;

        public JwtSubject() {
        }

        public JwtSubject(String id) {
            this.id = id;
        }


        public JwtSubject setId(String id) {
            this.id = id;
            return this;
        }

        public JwtSubject(int userid, String username, String roles) {
            this.userid = userid;
            this.username = username;
            this.roles = roles;
        }

        public JwtSubject(int userid, int deptid, String username, String roles) {
            this.userid = userid;
            this.deptid = deptid;
            this.username = username;
            this.roles = roles;
        }


        public JwtSubject(int userid, int deptid, String username, String roles, long lastlogin) {
            this.userid = userid;
            this.deptid = deptid;
            this.username = username;
            this.roles = roles;
            this.lastlogin = lastlogin;
        }

        public int getPid() {
            return pid;
        }

        public String getId() {
            return id;
        }

        public void setPid(int pid) {
            this.pid = pid;
        }

        public int getUserid() {
            return userid;
        }

        public void setUserid(int userid) {
            this.userid = userid;
        }

        public int getDeptid() {
            return deptid;
        }

        public void setDeptid(int deptid) {
            this.deptid = deptid;
        }

        public int getOrgid() {
            return orgid;
        }

        public void setOrgid(int orgid) {
            this.orgid = orgid;
        }

        public int getTempid() {
            return tempid;
        }

        public void setTempid(int tempid) {
            this.tempid = tempid;
        }

        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getRoles() {
            return roles;
        }

        public void setRoles(String roles) {
            this.roles = roles;
        }

        public String getPosts() {
            return posts;
        }

        public void setPosts(String posts) {
            this.posts = posts;
        }

        public long getLastlogin() {
            return lastlogin;
        }

        public void setLastlogin(long lastlogin) {
            this.lastlogin = lastlogin;
        }

        public String toJson() {
            return JSON.toJSONString(this);
        }
    }


    /**
     * jwt黑名单
     */
    public static class JwtPool {
        private static List JWTLIST = new ArrayList();

        public static void AddJwt(String jwt) {
            JWTLIST.add(jwt);
        }

        /**
         * @param jwt
         * @return
         */
        public static boolean checkJwt(String jwt) {
            for (int k = 0; k < JWTLIST.size(); k++) {
                String jwts = String.valueOf(JWTLIST.get(k));
                if (jwt.equals(jwts)) {
                    return true;
                }
            }
            return false;
        }
    }

    public static void main(String[] arg) {
//        String jwt = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMDAwMSIsInN1YiI6IntcImRlcHRpZFwiOjk5OTksXCJpZFwiOlwiNDAyODhhZjc4YjVmNzFiNzAxOGI1Zjc1MjkyNjAwMDJcIixcImxhc3Rsb2dpblwiOjE2OTgxMTM1OTU2ODYsXCJvcmdpZFwiOjEwMSxcInBpZFwiOjAsXCJwb3N0c1wiOlwifHwyfDF8fFwiLFwicm9sZXNcIjpcInxhZG1pbmlzdHJhdG9yfGFyZWFhZG1pbnxhcnRpY2xlYWRtaW58YnJhbmNoYWRtaW58Y2l0eWFkbWlufGdvb2RzYWRtaW58Z3JvdXBhZG1pbnxqZmFkbWlufGxvZ2lufHN5c3RlbXx3ZWl4aW58XCIsXCJ0ZW1waWRcIjowLFwidXNlcmlkXCI6MTAwMDEsXCJ1c2VybmFtZVwiOlwid3V5YW5nXCJ9IiwiaXNzIjoidXNlciIsImlhdCI6MTY5ODExMzU5NSwiZXhwIjoxNjk4MTM1MTk1fQ.pQT0Xu1vRO4vZQFQu1C1rFU9HdwzUUTcO7JLsjRj3aU";
//        jwt = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMDAwMSIsInN1YiI6IntcImRlcHRpZFwiOjk5OTksXCJpZFwiOlwiNDAyODgwZWE4YjYwZGIwZTAxOGI2MGRiNTI5MDAwMDFcIixcImxhc3Rsb2dpblwiOjE2OTgxMzcwNjgxNzYsXCJvcmdpZFwiOjEwMSxcInBpZFwiOjAsXCJwb3N0c1wiOlwifHwyfDF8fFwiLFwicm9sZXNcIjpcInxhZG1pbmlzdHJhdG9yfGFyZWFhZG1pbnxhcnRpY2xlYWRtaW58YnJhbmNoYWRtaW58Y2l0eWFkbWlufGdvb2RzYWRtaW58Z3JvdXBhZG1pbnxqZmFkbWlufGxvZ2lufHN5c3RlbXx3ZWl4aW58XCIsXCJ0ZW1waWRcIjowLFwidXNlcmlkXCI6MTAwMDEsXCJ1c2VybmFtZVwiOlwid3V5YW5nXCJ9IiwiaXNzIjoidXNlciIsImlhdCI6MTY5ODEzNzA2OCwiZXhwIjoxNjk4NjU1NDY4fQ.77gQWziKScoxdREiSO9FWKo4cSmP1c6GcF7YYthgEg4";
//        JwtSubject subject = JwtUtil.getJwtInfo(jwt);
//        System.out.println(subject);


        //  JwtUtil.createJWT("ffff", new JwtSubject(), LoginUtil.EXPRESS_LOGIN_TIME);
    }

}
